package com.ruoyi.workflow.dubbo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.ruoyi.common.core.utils.BeanCopyUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.workflow.constant.FlowConstant;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.workflow.api.RemoteWorkflowService;
import com.ruoyi.workflow.api.domain.vo.TaskModel;
import com.ruoyi.workflow.domain.vo.MultiVo;
import com.ruoyi.workflow.flowable.factory.WorkflowService;
import com.ruoyi.workflow.service.IUserService;
import com.ruoyi.workflow.utils.WorkFlowUtils;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.IdentityLinkInfo;
import org.flowable.task.api.Task;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 工作流通用业务管理
 *
 * @author gssong
 */
@RequiredArgsConstructor
@Service
@DubboService
public class RemoteWorkflowServiceImpl extends WorkflowService implements RemoteWorkflowService {

    private final IUserService iUserService;

    /**
     * @description: 设置流程变量
     * @param: taskId
     * @param: variableName
     * @param: value
     * @return: void
     * @author: gssong
     * @date: 2022/10/18 12:25
     */
    @Override
    public void setVariable(String taskId, String variableName, Object value) {
        WorkFlowUtils.setVariable(taskId, variableName, value);
    }

    /**
     * @description: 设置流程变量
     * @param: taskId
     * @param: variables
     * @return: void
     * @author: gssong
     * @date: 2022/12/9 20:10
     */
    @Override
    public void setVariables(String taskId, Map<String, Object> variables) {
        WorkFlowUtils.setVariables(taskId, variables);
    }

    /**
     * @description: 获取当前任务
     * @param: taskId
     * @return: com.ruoyi.workflow.api.domain.vo.TaskModel
     * @author: gssong
     * @date: 2022/12/9 20:10
     */
    @Override
    public TaskModel getCurrentTask(String taskId) {
        Task task = WorkFlowUtils.getCurrentTask(taskId);
        TaskModel taskModel = new TaskModel();
        if (task != null) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            BeanCopyUtils.copy(task, taskModel);
            taskModel.setStartUserId(processInstance.getStartUserId());
            taskModel.setBusinessKey(processInstance.getBusinessKey());

            List<Long> userIds = new ArrayList<>();
            if (StringUtils.isNotBlank(processInstance.getStartUserId())) {
                userIds.add(Long.valueOf(processInstance.getStartUserId()));
            }
            if (StringUtils.isNotBlank(task.getAssignee())) {
                userIds.add(Long.valueOf(task.getAssignee()));
            }
            if (CollUtil.isNotEmpty(userIds)) {
                List<SysUser> sysUsers = iUserService.selectListUserByIds(userIds);
                if (CollUtil.isNotEmpty(sysUsers)) {
                    sysUsers.stream().filter(e -> e.getUserId().toString().equals(taskModel.getAssignee())).findFirst().ifPresent(e -> taskModel.setAssignee(e.getNickName()));
                    sysUsers.stream().filter(e -> e.getUserId().toString().equals(taskModel.getStartUserId())).findFirst().ifPresent(e -> taskModel.setStartUserNickName(e.getNickName()));
                }
            }
            MultiVo multiInstance = WorkFlowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
            taskModel.setMultiInstance(multiInstance != null);

            List<IdentityLink> identityLinkList = WorkFlowUtils.getCandidateUser(task.getId());
            if (CollectionUtil.isNotEmpty(identityLinkList)) {
                List<String> collectType = identityLinkList.stream().map(IdentityLink::getType).collect(Collectors.toList());
                if (StringUtils.isBlank(task.getAssignee()) && collectType.size() > 1 && collectType.contains(FlowConstant.CANDIDATE)) {
                    taskModel.setIsClaim(false);
                } else if (StringUtils.isNotBlank(task.getAssignee()) && collectType.size() > 1 && collectType.contains(FlowConstant.CANDIDATE)) {
                    taskModel.setIsClaim(true);
                }
            }
        }
        return taskModel;
    }

    /**
     * @description: 获取当前任务
     * @param: processInstanceId
     * @return: java.util.List<com.ruoyi.workflow.api.domain.vo.TaskModel>
     * @author: gssong
     * @date: 2022/12/9 20:22
     */
    @Override
    public List<TaskModel> getCurrentTaskList(String processInstanceId) {
        List<Task> taskList = WorkFlowUtils.getCurrentTaskList(processInstanceId);

        List<TaskModel> taskModelList = new ArrayList<>();
        TaskModel taskModel = new TaskModel();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        List<Long> userIds;
        if (CollUtil.isNotEmpty(taskList)) {
            userIds = taskList.stream().filter(e -> e.getAssignee() != null).map(e -> Long.valueOf(e.getAssignee())).collect(Collectors.toList());
            userIds.add(Long.valueOf(processInstance.getStartUserId()));
            if (CollUtil.isEmpty(userIds)) {
                return taskModelList;
            }
            List<SysUser> sysUsers = iUserService.selectListUserByIds(userIds);
            for (Task task : taskList) {
                BeanCopyUtils.copy(task, taskModel);
                taskModel.setStartUserId(processInstance.getStartUserId());
                taskModel.setBusinessKey(processInstance.getBusinessKey());
                if (CollUtil.isNotEmpty(sysUsers)) {
                    sysUsers.stream().filter(e -> e.getUserId().toString().equals(taskModel.getAssigneeId().toString())).findFirst().ifPresent(e -> taskModel.setAssignee(e.getNickName()));
                    sysUsers.stream().filter(e -> e.getUserId().toString().equals(taskModel.getStartUserId())).findFirst().ifPresent(e -> taskModel.setStartUserNickName(e.getNickName()));
                }
                MultiVo multiInstance = WorkFlowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
                taskModel.setMultiInstance(multiInstance != null);

                List<IdentityLink> identityLinkList = WorkFlowUtils.getCandidateUser(task.getId());
                if (CollectionUtil.isNotEmpty(identityLinkList)) {
                    List<String> collectType = identityLinkList.stream().map(IdentityLink::getType).collect(Collectors.toList());
                    if (StringUtils.isBlank(task.getAssignee()) && collectType.size() > 1 && collectType.contains(FlowConstant.CANDIDATE)) {
                        taskModel.setIsClaim(false);
                    } else if (StringUtils.isNotBlank(task.getAssignee()) && collectType.size() > 1 && collectType.contains(FlowConstant.CANDIDATE)) {
                        taskModel.setIsClaim(true);
                    }
                }
                taskModelList.add(taskModel);
            }
        }

        return taskModelList;
    }

    /**
     * @description: 获取当前任务审批人
     * @param: taskId
     * @return: java.util.List<java.lang.String>
     * @author: gssong
     * @date: 2022/12/9 20:32
     */
    @Override
    public List<String> getCurrentApprover(String taskId) {
        List<IdentityLink> identityLinkList = WorkFlowUtils.getCurrentApprover(taskId);
        if (CollUtil.isNotEmpty(identityLinkList)) {
            return identityLinkList.stream().map(IdentityLinkInfo::getUserId).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }
}
